package edu.whu.rose.clock.ssql.index;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashSet;

import com.sleepycat.je.Cursor;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;

import edu.whu.rose.clock.setup.GraphDB;
import edu.whu.rose.clock.setup.IndexEnvironment;
import edu.whu.rose.clock.ssql.graphindex.GraphIndexManager;

public class VertexInvertedList {

	//database
	private VertexIndexDB idb;
	
	//cache
	private VertexIndexCache ic;
	
	private HashSet<String> stopwordlist;
	
	public VertexInvertedList(Environment dbEnv) {
		idb = new VertexIndexDB(dbEnv);
	}
	
	public VertexInvertedList(Environment dbEnv, String dbName) {
		idb = new VertexIndexDB(dbEnv, dbName);
	}
	
	public static void main(String[] args) {
		File file = new File("dbEnv_vertexindex");
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				files[i].delete();
			}
		}
		
		file = new File("graph/vertex.txt");
		IndexEnvironment ie = new IndexEnvironment("dbEnv_vertexindex");
		if (!ie.openEnv()) {
			System.exit(1);
		}
		VertexInvertedList vil = new VertexInvertedList(ie.getEnvironment());
		vil.init();
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			Date startTime = new Date();
			vil.createIndex(br);
			Date endTime = new Date();
			System.out.println("Completed indexing. The time spent is " + (endTime.getTime() - startTime.getTime()) + "ms");
			br.close();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
		vil.close();
		ie.closeEnv();
	}
	
	public void init() {
		if (!idb.openDB()) {
			System.exit(1);
		}
		ic = new VertexIndexCache(idb, 3000000);
		stopwordlist = new HashSet<String>();
		try {
			BufferedReader br = new BufferedReader(new FileReader("stop word list.txt"));
			while (br.ready()) {
				stopwordlist.add(br.readLine().trim());
			}
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	public void close() {
		idb.closeDB();
	}
	
	public void createIndex(BufferedReader br) {
		int counter = 0;
		Date sDate = new Date();
		Date eDate = null;
		try {
			while (br.ready()) {
				String line = br.readLine().trim();
				if (line.length() > 0) {
					int pos = line.indexOf(" ");
					if (pos == -1) {
						System.out.println("Found wrong line: " + line);
						continue;
					}
					String key = line.substring(0, pos);
					String value = line.substring(pos).trim();
					this.insertVertex(key, value);
					counter++;
					if (counter % 10000 == 0) {
						System.out.println(key);
						eDate = new Date();
						System.out.println("Time exhausted: " + (eDate.getTime() - sDate.getTime()) + " ms");
						sDate = eDate;
						ic.statistic();
					}
				}
			}
			ic.flush();
			ic.statistic();
		}
		catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		catch (DatabaseException ex) {
			ex.printStackTrace();
		}
	}
	
	public void createIndex(GraphDB gdb) {
		Cursor cursor = null;
		DatabaseEntry key = new DatabaseEntry();
		DatabaseEntry value = new DatabaseEntry();
		try {
			int counter = 0;
			cursor = gdb.getVertex().openCursor(null, null);
			Date sDate = new Date();
			Date eDate = null;
			while (cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
				String strKey = new String(key.getData(), "UTF-8");
				String strValue = new String(value.getData(), "UTF-8");
				insertVertex(strKey, strValue);
				counter++;
				if (counter % 10000 == 0) {
					System.out.println(strKey);
					eDate = new Date();
					System.out.println("Time exhausted: " + (eDate.getTime() - sDate.getTime()) + " ms");
					sDate = eDate;
					ic.statistic();
				}
			}
			ic.flush();
			ic.statistic();
		}
		catch (DatabaseException ex) {
			ex.printStackTrace();
		}
		catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		finally {
			try {
				if (cursor != null) {
					cursor.close();
				}
			}
			catch (DatabaseException ex) {
				ex.printStackTrace();
				System.err.println("Error: closing cursor");
			}
		}
	}
	
	public void insertVertex(String key, String value) {
		String[] pairs = value.split("@@");
		for (int i = 0; i < pairs.length; i++) {
			String pair = pairs[i].trim();
			if (pair.length() > 0) {
				int pos = pair.indexOf(":");
				if (pos == -1) {
					System.out.println("Found wrong attr-value pair: " + pair);
					continue;
				}
				String attrName = pair.substring(0, pos).trim();
				String attrValue = pair.substring(pos + 1).trim();
				String[] keywords = null;
				if (attrName.equals("title")) {
					keywords = GraphIndexManager.parse(attrValue);
				} else if (attrName.equals("name")) {
					keywords = GraphIndexManager.naiveParse(attrValue);
				} else {
					continue;
				}
				for (int j = 0; j < keywords.length; j++) {
					String keyword = keywords[j].trim();
					if (keyword.length() > 0) {
						String lcKeyword = keyword.toLowerCase();
						if (stopwordlist.contains(lcKeyword)) {
							continue;
						}
//						String keyword_attr = keyword + "@@" + attrName;
						try {
							ic.initInsert(lcKeyword, key);
//							ic.initInsert(keyword_attr, key);
						}
						catch (DatabaseException ex) {
							ex.printStackTrace();
						}
						catch (UnsupportedEncodingException ex) {
							ex.printStackTrace();
						}
					}
				}
			}
		}
	}

}
